package ar.edu.unlu.sistemas.p2p.business.util;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import ar.edu.unlu.sistemas.p2p.business.vo.TermFrecuencyVO;
import ar.edu.unlu.sistemas.p2p.business.vo.WordVO;

public class Indexer {
	
	private static Collection<String> stopWords;
	
	private static Collection<String> getStopWords() {
		if (stopWords == null) {
			stopWords = new ArrayList<String>();
			try {
				InputStream is = Indexer.class.getResourceAsStream("stopwords.txt");
				byte[] bArray = new byte[is.available()];
				is.read(bArray);
				Logger.logDebug(Indexer.class.getSimpleName(), "stopwords.txt"+bArray.length);
				String[] sArray = StringUtils.tokenize(new String(bArray));

				for (int i=0;i<sArray.length;i++) {
					stopWords.add(sArray[i]);
				}
				Logger.logInfo(Indexer.class.getSimpleName(), "Se cargaron las stopWords "+stopWords.toString());
			} catch (Exception e) {
				Logger.logError(Indexer.class.getSimpleName(), "Fallo el levantado de la stopWords",e);
			}
		}
		return stopWords;
	}

	/**
	 * Obtiene el término con máxima frecuencia. Luego normaliza todos los tfs con el valor
	 * de este término obtenido. También calcula la suma de cuadrados.
	 * 
	 * @param index
	 * @param booleano que indica si se procesa una query
	 */
	private static void tfMaxCalulate(HashMap<String,TermFrecuencyVO> index, boolean isAQuery) {
		TermFrecuencyVO term;
		Double squareSum = new Double(0);
		List<TermFrecuencyVO> values = new ArrayList<TermFrecuencyVO>(index.values());
		Collections.sort(values, new TermComparator());
		Iterator<TermFrecuencyVO> list =  (Iterator<TermFrecuencyVO>)values.iterator();
		TermFrecuencyVO maxTerm = list.next();
		maxTerm.setFreq(maxTerm.getValue().intValue());
		System.out.println("//Término Máximo// "+maxTerm.getWord().getName()+" / "+maxTerm.getValue()+" /");
		while (list.hasNext()) {
			term = list.next();
			if (term.getValue() < Params.MIN_FRECUENCY && !isAQuery) {
				index.remove(term.getWord().getName());
			} else {
				term.setFreq(term.getValue().intValue());
				term.setValue(term.getValue()/maxTerm.getValue());
				squareSum += Math.pow(term.getValue(), 2);
			}
		}
		maxTerm.setValue(new Float(1));
		squareSum += maxTerm.getValue();
		index.put(Constants.SQUARE_SUM_WORD, new TermFrecuencyVO(new WordVO(Constants.SQUARE_SUM_WORD), squareSum.floatValue()));
	}
	
	/**
	 * Método principal de la clase indexer. A partir de un archivo de texto, se lo indexa en la base
	 * de datos mediante la representación del modelo vectorial.
	 * 
	 * @param file
	 * @return Un diccionario con la key que es el término y el valor el objeto q lo representa
	 * @throws FileNotFoundException
	 * @throws IOException
	 * @throws UnsupportedEncodingException
	 */
	public static HashMap<String,TermFrecuencyVO> createIndexFromFile(FileReader file) throws FileNotFoundException,IOException, UnsupportedEncodingException {
		String line;
		TermFrecuencyVO term;
		HashMap<String,TermFrecuencyVO> index = new HashMap<String,TermFrecuencyVO>();
		BufferedReader in = new BufferedReader(file);
			while ((line = in.readLine()) != null) {
				String[] tokens = StringUtils.tokenize(line);
				for (int i=0;i<tokens.length;i++) {
					if (index.containsKey(tokens[i])) {
						term = index.get(tokens[i]);
						term.setValue(term.getValue()+1);
					} else {
						if (!(tokens[i].length() < Params.MIN_FRECUENCY) && (!getStopWords().contains(tokens[i]))) {
							index.put(tokens[i], new TermFrecuencyVO(new WordVO(tokens[i]),new Float(1)));
						}
					}
				}
			}
			tfMaxCalulate(index,false);
			return index;
	}
	
	/**
	 * Indexa una consulta
	 * 
	 * @param query
	 * @return el diccionario de la consulta indexada para la el cálculo de la métrica del coseno
	 * @throws UnsupportedEncodingException
	 */
	public static HashMap<String,TermFrecuencyVO> indexQuery(String query) throws UnsupportedEncodingException {
		TermFrecuencyVO term;
		HashMap<String,TermFrecuencyVO> index = new HashMap<String,TermFrecuencyVO>();
		String[] tokens = StringUtils.tokenize(query);
		for (int i=0;i<tokens.length;i++) {
			if (index.containsKey(tokens[i])) {
				term = index.get(tokens[i]);
				term.setValue(term.getValue()+1);
			} else {
				index.put(tokens[i], new TermFrecuencyVO(new WordVO(tokens[i]),new Float(1)));
			}
		}
		tfMaxCalulate(index,true);
		return index;
	}
	
}
